#include "RendererWorker.h"
#include "ChunkRenderer.h"
#include "ChunkCacheProvider.h"

PrimitiveRendererBase *RendererWorker::RenderChunk(const int &x, const int &z)
{
	ChunkRenderer ren(Renderer->GetSchematic());

	PrimitiveRendererBase *tex = Renderer->CreatePrimitiveRenderer();
	tex->CullProvider = Renderer;
	tex->LightProvider = Renderer;
	ChunkCacheProvider cache(Point2i(x, z));
	tex->CacheProvider = &cache;
	ren.ProgressReporter = tex->ProgressReporter = this;
	ren.RenderChunk(tex, Point3i(x * 16, 0, z * 16), Point3i(16, Renderer->GetSchematic()->Height, 16));
	tex->Compile(false);

	return tex;
}

void *RendererWorker::Entry()
{
	while (true)
	{
restart:
		{
			wxMutexLocker lock(WorkerCloseMutex);

			if (GetThread()->TestDestroy() || ShouldQuit)
				break;

			Point2i pos;

			{
				wxMutexLocker locker(ChunksAccessLock);
			
				if (ChunksToRender.size() == 0)
				{
					Status = "Waiting";
					goto sleep;
				}

				pos = ChunksToRender.front();
				ChunksToRender.pop();
			}

			auto p = (pos.Y * Renderer->GetSchematic()->WidthInChunks) + pos.X;
		
			switch (Renderer->RenderQueueType(p))
			{
			case 0:
				break;
			case 1:
				Renderer->RenderFinished(p, RenderChunk(pos.X, pos.Y));
				break;
			case 2:
				{
					auto r = Renderer->GetChunkRender(p);

					ChunkCacheProvider cache(Point2i(pos.X, pos.Y));
					r->CacheProvider = &cache;

					r->ProgressReporter = this;
					r->Compile(true);
				}
				Renderer->Refresh();
				break;
			}

			Renderer->SetRenderQueueType(p, 0);
			goto restart;
		}

sleep:
		{
			wxMutexLocker lock(WorkerLock);
			WorkerCondition.WaitTimeout(1000);
		}
	}

	return nullptr;
}